package cn.smile.utils;

import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * @Author: 毛苏宇
 * @Description: You can do it!    Json与Java复杂类型的相互转换
 * 1.Json转Java对象
 * 2.对象转Json字符串
 * 3.Json转List集合
 * 4.List集合转Json
 * 5.Json转Set集合
 * 6.Set集合转Json
 * 7.Json转Map集合
 * 8.Map集合转Json
 * @Date: Create in 16:50 2019/2/20
 * 依赖：
 *          <!--Json转换需要的依赖-->
 *         <dependency>
 *             <groupId>com.google.code.gson</groupId>
 *             <artifactId>gson</artifactId>
 *             <version>2.8.0</version>
 *         </dependency>
 *         <dependency>
 *             <groupId>com.fasterxml.jackson.core</groupId>
 *             <artifactId>jackson-databind</artifactId>
 *             <version>2.8.3</version>
 *         </dependency>
 */
@Component
public final class GsonTool<T, E> {
    /**
     * T 代表map键的类型
     * E 代表map值的类型
     * 如果不知道怎么配置，则都为Object，建议添加
     */



    /**
     * 自行配置
     */
    private final Gson gson = new GsonBuilder()
            //当字段值为空或null时，依然对该字段进行转换
            .serializeNulls()
            //防止特殊字符出现乱码
            .disableHtmlEscaping()
            //对结果进行换行
            .setPrettyPrinting()
            //时间转化为特定格式
            .setDateFormat("yyyy-MM-dd HH:mm:ss:SSS")
            //使用这些配置创建Gson对象
            .create();


    /**
     * Java对象转为Json
     *
     * @param object java对象
     * @return 返回Json
     */
    public final String objectToJson(E object) {
        return gson.toJson(object);
    }


    /**
     * List集合转Json
     *
     * @param list List集合
     * @return 返回Json
     */
    public final String listToJson(List<E> list) {
        return gson.toJson(list);
    }

    /**
     * map集合转Json
     *
     * @param map map集合
     * @return 返回Json
     */
    public String mapToJson(Map<T, E> map) {
        return gson.toJson(map);
    }

    /**
     * set集合转Json
     *
     * @param set set集合
     * @return 返回Json
     */
    public String setToJson(Set<E> set) {
        return gson.toJson(set);
    }


    /**
     * Json转Java对象
     *
     * @param json      Json字符串
     * @param typeClass 对象类类型
     * @return 返回Java对象
     */
    public E jsonToObject(String json, Class<E> typeClass) {
        //先转为泛型
        E object = gson.fromJson(json, typeClass);
        //返回该泛型,无需做类型转换
        return object;
    }

    /**
     * Json转List集合,当对象中存在Date类型时请使用@JsonFormat( pattern="yyyy-MM-dd HH:mm:ss:SSS")注解修饰该Date属性
     *
     * @param json      Json字符串
     * @param typeClass 类类型
     * @return 返回List集合
     */
    public List<E> jsonToList(String json, Class<E> typeClass) {
        //ObjectMapper将转换成Java对象匹配JSON结构
        ObjectMapper mapper = new ObjectMapper();
        //得到Java类型
        JavaType javaType = mapper.getTypeFactory().constructParametricType(List.class, typeClass);
        try {
            //将json中的数据装配到该结构中并返回
            return mapper.readValue(json, javaType);
        } catch (Exception e) {
            e.printStackTrace();
            //出错则返回
            return null;
        }
    }

    /**
     * Json转Set集合
     *
     * @param json      Json字符串
     * @param typeClass 类类型
     * @return 返回Set集合
     */
    public Set<E> jsonToSet(String json, Class<E> typeClass) {
        //ObjectMapper将转换成Java对象匹配JSON结构
        ObjectMapper mapper = new ObjectMapper();
        //得到Java类型
        JavaType javaType = mapper.getTypeFactory().constructParametricType(Set.class, typeClass);
        try {
            //将json中的数据装配到该结构中并返回
            return mapper.readValue(json, javaType);
        } catch (Exception e) {
            e.printStackTrace();
            //出错则返回
            return null;
        }
    }


    /**
     * Json转Map集合
     *
     * @param json      Json字符串
     * @param keyType   key的类类型
     * @param valueType 值的类类型
     * @return 返回map集合
     */
    public Map<T, E> jsonToMap(String json, Class<T> keyType, Class<E> valueType) {
        //ObjectMapper将转换成Java对象匹配JSON结构
        ObjectMapper mapper = new ObjectMapper();
        //得到Java类型
        JavaType javaType = mapper.getTypeFactory().constructParametricType(Map.class, keyType, valueType);
        try {
            //将json中的数据装配到该结构中并返回
            return mapper.readValue(json, javaType);
        } catch (Exception e) {
            e.printStackTrace();
            //出错则返回
            return null;
        }
    }


}
